//+------------------------------------------------------------------+
//|                          Tree.mqh 二叉树类头文件                 |
//|                版权所有 2000-2025, MetaQuotes Ltd.              |
//|                        官方网址: https://www.mql5.com            |
//+------------------------------------------------------------------+
#include "TreeNode.h"  // 引入二叉树节点类头文件，CTree 管理 CTreeNode 及其派生类实例
//+------------------------------------------------------------------+
//| CTree 类                                                         |
//| 功能：平衡二叉树管理类，用于构建和操作 CTreeNode 实例组成的二叉树 |
//| 核心特性：                                                      |
//|  1. 自动维护二叉树平衡（插入/删除节点后触发平衡调整，避免链表化）  |
//|  2. 支持节点的插入、分离、删除、清空，以及高效查找（基于二叉树特性） |
//|  3. 提供树结构的文件序列化/反序列化，支持节点数据持久化           |
//| 继承关系：派生自 CTreeNode 类，可作为特殊节点参与树结构，但主要承担树管理职责 |
//+------------------------------------------------------------------+
class CTree : public CTreeNode
  {
protected:
   CTreeNode        *m_root_node;        // 二叉树的根节点指针（CTreeNode 实例，树的唯一入口）

public:
   /**
    * @brief 构造函数：初始化 CTree 二叉树实例
    * @details 初始化根节点指针为 NULL（空树），其他继承自 CTreeNode 的成员变量按基类规则初始化
    */
                     CTree(void);

   /**
    * @brief 析构函数：销毁 CTree 二叉树实例
    * @details 调用 Clear 方法清空整个树，释放所有动态分配的 CTreeNode 实例内存（避免内存泄漏）
    */
                    ~CTree(void);

   //--- 保护成员变量访问方法（只读）
   /**
    * @brief 获取二叉树的根节点指针
    * @return CTreeNode* - 根节点指针，空树返回 NULL
    */
   CTreeNode        *Root(void) const { return(m_root_node); }

   //--- 对象类型识别方法
   /**
    * @brief 获取当前二叉树对象的类型标识（用于区分其他 CTreeNode 派生类）
    * @return int - 类型标识，固定返回 0x9999（MQL5 二叉树类专属标识）
    */
   virtual int       Type() const { return(0x9999); }

   //--- 二叉树填充方法（插入节点）
   /**
    * @brief 向二叉树中插入一个 CTreeNode 实例节点
    * @details 按二叉树规则（基于 CTreeNode::Compare 方法判断节点大小关系）确定插入位置，
    *          插入后自动触发树平衡调整（避免树结构退化）
    * @param new_node [in] 要插入的 CTreeNode 实例指针（需确保指针有效，且节点未被其他树管理）
    * @return CTreeNode* - 操作结果：成功插入返回新节点指针；若节点已存在（Compare 返回 0），返回已存在节点指针；失败返回 NULL
    */
   CTreeNode        *Insert(CTreeNode *new_node);

   //--- 二叉树节点删除/分离方法
   /**
    * @brief 从二叉树中分离指定节点（仅移除节点与树的关联，不释放节点内存）
    * @details 分离后自动触发树平衡调整，节点仍可被其他树重新插入或手动释放
    * @param node [in] 要分离的 CTreeNode 实例指针（需确保指针有效且属于当前树）
    * @return bool - 操作结果：成功分离返回 true，节点无效/不属于当前树返回 false
    */
   bool              Detach(CTreeNode *node);

   /**
    * @brief 从二叉树中删除指定节点（移除关联并释放节点内存，仅对动态分配的节点有效）
    * @details 先调用 Detach 分离节点，若节点是动态分配（POINTER_DYNAMIC），则调用 delete 释放内存
    * @param node [in] 要删除的 CTreeNode 实例指针（需确保指针有效且属于当前树）
    * @return bool - 操作结果：成功删除（含内存释放）返回 true，节点无效/不属于当前树返回 false
    */
   bool              Delete(CTreeNode *node);

   /**
    * @brief 清空整个二叉树（删除所有节点并释放内存）
    * @details 递归删除所有节点（从根节点开始），释放所有动态分配的 CTreeNode 实例内存，
    *          清空后根节点指针重置为 NULL（树变为空）
    */
   void              Clear(void);

   //--- 二叉树查找方法
   /**
    * @brief 在二叉树中查找与目标节点匹配的节点（基于 CTreeNode::Compare 方法）
    * @details 利用二叉树特性高效查找（时间复杂度 O(log n)），Compare 返回 0 表示匹配
    * @param node [in] 目标节点指针（用于提供匹配基准，需确保指针有效）
    * @return CTreeNode* - 查找结果：找到匹配节点返回对应指针，未找到返回 NULL
    */
   CTreeNode        *Find(const CTreeNode *node);

   //--- 二叉树节点创建方法（需派生类重写，创建具体 CTreeNode 派生类实例）
   /**
    * @brief 创建二叉树节点对应的 CTreeNode 实例（纯虚函数逻辑，需用户在派生类中重写）
    * @details 基类默认返回 NULL，派生类需实现为创建具体节点对象（如 CMyTreeNode *CreateElement() { return new CMyTreeNode; }）
    * @return CTreeNode* - 新创建的 CTreeNode 实例指针；基类默认返回 NULL，必须在派生类中重写才能正常使用 Load 方法
    */
   virtual CTreeNode *CreateElement() { return(NULL); }

   //--- 文件操作相关方法（树结构整体序列化/反序列化）
   /**
    * @brief 将二叉树及其所有节点（CTreeNode 实例）的数据写入指定文件
    * @details 从根节点开始，调用每个节点的 SaveNode 方法递归写入节点数据（含子节点）
    * @param file_handle [in] 已打开的文件句柄（需包含写入权限，建议用 FILE_BIN 二进制模式）
    * @return bool - 操作结果：true 表示树及所有节点均写入成功，false 表示文件句柄无效/写入失败
    */
   virtual bool      Save(const int file_handle);

   /**
    * @brief 从指定文件读取数据并重建二叉树（含所有节点 CTreeNode 实例）
    * @details 先清空当前树，通过 CreateElement 创建根节点，再调用根节点的 LoadNode 方法递归读取所有子节点数据
    * @param file_handle [in] 已打开的文件句柄（需包含读取权限，建议用 FILE_BIN 二进制模式）
    * @return bool - 操作结果：true 表示树及所有节点均读取成功，false 表示文件句柄无效/创建根节点失败/读取失败
    */
   virtual bool      Load(const int file_handle);

protected:
   /**
    * @brief 二叉树平衡调整方法（内部使用，不对外暴露）
    * @details 当节点插入/删除导致树失衡时（左右子树高度差超过 1），通过旋转（左旋/右旋/双旋）调整树结构，
    *          确保树的平衡状态，维持高效查找性能
    * @param node [in] 失衡检测的起始节点（通常为插入/删除节点的祖先节点）
    */
   void              Balance(CTreeNode *node);
  };
//+------------------------------------------------------------------+